Partie 9 Manipuler les données
dplyr est une extension facilitant le traitement et la manipulation de données contenues dans une ou plusieurs tables (qu’il s’agisse de data frame ou de tibble). Elle propose une syntaxe claire et cohérente, sous formes de verbes, pour la plupart des opérations de ce type. Par ailleurs, les fonctions de dlpyr sont en général plus rapides que leur équivalent sous R de base, elles permettent donc de traiter des données de grande dimension.
9.1 Préparation
dplyr fait partie du tidyverse, elle est donc chargée automatiquement avec :
library(tidyverse)On peut également la charger explicitement avec :
library(dplyr)Dans ce qui suit on utilisera les données du jeu de données nycflights13. Celui-ci correspond aux données de tous les vols au départ d’un des trois aéroports de NEw-York en 2013. Il est réparti en trois tables :
flightscontient des informations sur le vol : date, départ, destination, horaires, retard…airportscontient des informations sur les aéroportsairlinescontient des données sur les compagnies aériennes
On va charger les trois tables du jeu de données :
library(nycflights13)
## Chargement des trois tables du jeu de données
data(flights)
data(airports)
data(airlines)9.2 Les verbes de dplyr
La manipulation de données avec dplyr se fait en utilisant un nombre réduit de verbes, qui correspondent chacun à une action différente appliquée à un tableau de données.
9.2.1 slice
Le verbe slice sélectionne des lignes du tableau selon leur position. On lui passe un chiffre ou un vecteur de chiffres.
Si on souhaite sélectionner la 345e ligne du tableau airports :
slice(airports, 345)Si on veut sélectionner les 5 premières lignes :
slice(airports, 1:5)9.2.2 filter
filter sélectionne des lignes d’un tableau de données selon une condition. On lui passe en paramètre un test, et seules les lignes pour lesquelles ce test renvoie vrai sont conservées.7
Si on veut choisir les vols du mois de janvier :
filter(flights, month == 1)Si on veut les vols avec un retard au départ compris entre 10 et 15 minutes :
filter(flights, dep_delay >= 10 & dep_delay <= 15)Si on passe plusieurs arguments à filter, celui-ci rajoute automatiquement une condition et. La ligne ci-dessus peut donc également être écrite de la manière suivante, avec le même résultat :
filter(flights, dep_delay >= 10, dep_delay <= 15)9.2.3 select et rename
select permet de sélectionner des colonnes d’un tableau de données. Ainsi, si on veut extraire les colonnes latet lon du tableau airports :
select(airports, lat, lon)Si on fait précéder le nom d’un -, la colonne est éliminée plutôt que sélectionnée :
select(airports, -lat, -lon)select comprend toute une série de fonctions facilitant la sélection de multiples colonnes. Par exemple, starts_with, ends_width, contains ou matches permettent d’exprimer des conditions sur les noms de variables :
select(airports, starts_with("dep_"))select peut être utilisée pour réordonner les colonnes d’une table. Par exemple, si on souhaite faire passer la colonne name en première position de la table airports, on peut faire :
select(airports, name, everything())Une variante de select est rename, qui permet de renommer facilement des colonnes. On l’utilise en lui passant des paramètres de la forme nouveau_nom = ancien_nom :
rename(airports, longitude = lon, latitude = lat)Si les noms de colonnes comportent des espaces ou des caractères spéciaux, on peut les entourer de guillemets (") ou de quotes inverses (`).
9.2.4 arrange
arrange réordonne les lignes d’un tableau selon une ou plusieurs colonnes.
Ainsi, si on veut trier le tableau flights selon le retard au départ croissant :
arrange(flights, dep_delay)On peut trier selon plusieurs colonnes. Par exemple selon le mois, puis selon le retard au départ :
arrange(flights, month, dep_delay)Si on veut trier selon une colonne par ordre décroissant, on lui applique la fonction desc() :
arrange(flights, desc(dep_delay))Combiné avec slice, arrange permet par exemples de sélectionner les trois vols ayant eu le plus de retard :
flights <- arrange(flights, desc(dep_delay))
slice(flights, 1:3)9.2.5 mutate
mutate permet de créer de nouvelles colonnes dans le tableau de données à partir des variables existantes.
Par exemple, la table airports contient l’altitude de l’aéroport en pieds. Si on veut créer une nouvelle variable avec l’altitude en mètres :
airports <- mutate(airports, alt_m = alt / 3.2808)
select(airports, name, alt, alt_m)On peut indiquer plusieurs nouvelles colonnes en une seule fois, et les expressions successives peuvent prendre en compte les résultats des calculs précédents.
flights <- mutate(flights,
distance_km = distance / 0.62137,
vitesse = distance_km / air_time * 60)
select(flights, distance, distance_km, vitesse)9.3 Enchaîner les opérations avec le pipe : %>%
Quand on manipule un tableau de données, il est fréquent d’enchaîner plusieurs opérations. On va par exemple filtrer une sous-population, sélectionner des colonnes et trier selon une variable.
Dans ce cas on peut le faire de deux manières différentes. La première est d’effectuer toutes les opérations en une fois en les “emboîtant” :
arrange(select(filter(flights, dest == "LAX"), dep_delay, arr_delay), dep_delay)Cette notation a plusieurs inconvénients :
- elle est peu lisible
- les opérations apparaissent dans l’ordre inverse de leur réalisation. Ici on effectue d’abord le
filter, puis leselect, puis learrange, alors qu’à la lecture du code c’est learrangequi apparaît en premier. - Il est difficile de voir quel paramètre se rapporte à quelle fonction
Une autre manière de faire est d’effectuer les opérations les unes après les autres, en sotckant les résultats intermédiaires dans un objet temporaire :
tmp <- filter(flights, dest == "LAX")
tmp <- select(tmp, dep_delay, arr_delay)
arrange(tmp, dep_delay)C’est nettement plus lisible, l’ordre des opérations est le bon, et les paramètres sont bien rattachés à leur fonction. Par contre, ça reste un peu “verbeux”, et on crée un objet temporaire dont on n’a pas réellement besoin.
Pour simplifier et améliorer encore la lisibilité du code, on va utiliser un nouvel opérateur, baptisé pipe.8 Le pipe se note %>%, et son fonctionnement est le suivant : si j’exécute expr %>% f, alors le résultat de l’expression expr, à gauche du pipe, sera passé comme premier argument à la fonction f, à droite du pipe, ce qui revient à exécuter f(expr).
Ainsi les deux expressions suivantes sont rigoureusement équivalentes :
filter(flights, dest == "LAX")flights %>% filter(dest == "LAX")Ce qui est intéressant dans l’histoire, c’est qu’on va pouvoir enchaîner les pipes. Plutôt que d’écrire :
select(filter(flights, dest == "LAX"), dep_delay, arr_delay)On va pouvoir faire :
flights %>% filter(dest == "LAX") %>% select(dep_delay, arr_delay)À chaque fois, le résultat de ce qui se trouve à gauche du pipe est passé comme premier argument à ce qui se trouve à droite. Le résultat final est le même, mais l’ordre des opérations correspond à l’ordre naturel de leur exécution, et on n’a pas eu besoin de créer d’objets intermédiaires.
Si la liste des fonctions enchaînées est longue, on peut les répartir sur plusieurs lignes à condition que l’opérateur %>% soit en fin de ligne :
flights %>%
filter(dest == "LAX") %>%
select(dep_delay, arr_delay) %>%
arrange(dep_delay)Enfin, on peut récupérer le résultat final de l’ensemble de la chaîne de fonctions pour, par exemple, le stocker dans un objet. On peut donc faire quelque chose comme ça :
delay_la <- flights %>%
filter(dest == "LAX") %>%
select(dep_delay, arr_delay) %>%
arrange(dep_delay)Dans ce cas, delay_la contiendra le tableau final, obtenu après application des trois instructions filter, select et arrange.
Cette utilisation du pipe n’est pas obligatoire, mais elle rend les scripts plus lisibles et plus rapides à saisir. On l’utilisera donc dans ce qui suit.
9.4 Opérations groupées
9.4.1 group_by
Un élément très important de dplyr est la fonction group_by. Elle permet de définir des groupes de lignes à partir des valeurs d’une ou plusieurs colonnes. Par exemple, on peut grouper les vols selon leur mois :
flights %>% group_by(month)Par défaut ceci ne fait rien de visible, à part l’apparition d’une mention Groups lors de l’affichage. Mais à partir du moment où des groupes ont été définis, les verbes comme slice, mutate ou summarise vont en tenir compte lors de leurs calculs.
Par exemple, si on applique slice à un tableau préalablement groupé, il va sélectionner les lignes aux positions indiquées pour chaque groupe :
flights %>% group_by(month) %>% slice(1)Idem pour mutate : les opérations appliquées lors du calcul des valeurs des nouvelles colonnes sont aplliquée groupe de lignes par groupe de lignes. Dans l’exemple suivant, on ajoute une nouvelle colonne qui contient le retard maximum du mois correspondant :
flights %>%
group_by(month) %>%
mutate(max_delay_month = max(dep_delay, na.rm = TRUE)) %>%
select(dep_delay, month, max_delay_month)Attention : la clause group_by marche pour les verbes déjà vus précédemment, sauf pour arrange, qui par défaut trie la table sans tenir compte des groupes. Pour obtenir un tri par groupe, il faut lui ajouter l’argument .by_group = TRUE.
On peut voir la différence en comparant les deux résultats suivants :
flights %>%
group_by(month) %>%
arrange(desc(dep_delay))flights %>%
group_by(month) %>%
arrange(desc(dep_delay), .by_group = TRUE)9.4.2 summarise et count
summarise permet d’agréger les lignes du tableau en effectuant une opération “résumée” sur une ou plusieurs colonnes. Par exemple, si on souhaite connaître les retards moyens au départ et à l’arrivée pour l’ensemble des vols du tableau flights :
flights %>%
summarise(retard_dep = mean(dep_delay, na.rm=TRUE),
retard_arr = mean(arr_delay, na.rm=TRUE))Cette fonction est en général utilisée avec group_by, puisqu’elle permet du coup d’agréger et résumer les lignes du tableau groupe par groupe. Si on souhaite calculer le délai maximum, le délai minimum et le délai moyen au départ pour chaque mois, on pourra faire :
flights %>%
group_by(month) %>%
summarise(max_delay = max(dep_delay, na.rm=TRUE),
min_delay = min(dep_delay, na.rm=TRUE),
mean_delay = mean(dep_delay, na.rm=TRUE))summarise dispose d’un opérateur spécial, n(), qui retourne le nombre de lignes du groupe. Ainsi si on veut le nombre de vols par destination :
flights %>%
group_by(dest) %>%
summarise(nb = n()) %>%
arrange(desc(nb))n() peut aussi être utilisée avec filter et mutate.
À noter que quand on veut compter le nombre de lignes par groupe, on peut utiliser directement la fonction count. Ainsi le code suivant est identique au précédent :
flights %>%
count(dest) %>%
arrange(desc(n))On peut également compter selon plusieurs variables :
flights %>%
count(origin, dest) %>%
arrange(desc(n))9.4.3 Grouper selon plusieurs variables
On peut grouper selon plusieurs variables à la fois, il suffit de les indiquer dans la clause du group_by :
flights %>%
group_by(month, dest) %>%
summarise(nb = n()) %>%
arrange(desc(nb))On peut utiliser plusieurs opérations de groupage dans la même série de fonctions. Ainsi, si on souhaite calculer le couple origine/destination avec le nombre maximum de vols selon le mois de l’année, on devra procéder en deux étapes : d’abord grouper selon mois et destination pour calculer le nombre de vols, puis grouper uniquement selon le mois pour sélectionner la ligne avec la valeur maximale.
flights %>%
group_by(month, origin, dest) %>%
summarise(nb = n()) %>%
group_by(month) %>%
filter(nb == max(nb))9.5 Autres fonctions utiles
dplyr contient beaucoup d’autres fonctions utiles pour la manipulation de données.
9.5.1 sample_n, sample_frac
Ces verbes permettent de sélectionner un nombre de lignes ou une fraction des lignes d’un tableau aléatoirement. Ainsi si on veut choisir 5 lignes au hasard dans le tableau airports :
airports %>% sample_n(5)Si on veut tirer au hasard 10% des lignes de flights :
flights %>% sample_frac(0.1)9.5.2 lead et lag
lead et lag permettent de décaler les observations d’une variable d’un cran vers l’arrière (pour lead) ou vers l’avant (pour lag).
lead(1:5)## [1] 2 3 4 5 NA
lag(1:5)## [1] NA 1 2 3 4
Ceci peut être utile pour des données de type “séries temporelles”. Par exemple, on peut facilement calculer l’écart entre chaque le retard au départ de chaque vol et celui du vol précédent :
flights %>%
mutate(dep_delay_prev = lead(dep_delay),
dep_delay_diff = dep_delay - dep_delay_prev) %>%
select(dep_delay_prev, dep_delay, dep_delay_diff)9.5.3 tally
tally est une fonction qui permet de compter le nombre d’observations d’un groupe :
flights %>%
group_by(month, origin, dest) %>%
tallyLors de son premier appel, elle sera équivalente à un summarise(n = n()). Là où la fonction est intelligente, c’est que si on l’appelle plusieurs fois successivement, elle prendra en compte l’existence d’un n déjà calculé et effectuera automatiquement un summarise(n = sum(n)) :
flights %>%
group_by(month, origin, dest) %>%
tally %>%
tally## Using `n` as weighting variable
9.5.4 distinct
distinct filtre les lignes du tableau pour ne conserver que les lignes distinctes, en supprimant toutes les lignes en double.
flights %>%
select(day, month) %>%
distinct9.5.5 do
do est un verbe supplémentaire générique qui permet d’appliquer des opérations complexes aux lignes d’un tableau.
9.6 Tables multiples
9.6.1 Concaténation : bind_rows et bind_cols
Les fonctions bind_rows et bind_cols permettent d’ajouter des lignes (respectivement des colonnes) à une table à partir d’une ou plusieurs autres tables.
L’exemple suivant (certes très artificiel) montre l’utilisation de bind_rows :
t1 <- airports %>% slice(1:2)
t2 <- airports %>% slice(5:6)
t3 <- airports %>% slice(100:101) %>% select(-tz, -dst)
bind_rows(t1, t2, t3, .id = "source")On remarquera que si des colonnes sont manquantes pour certaines tables, comme les colonnes tz et dst de t3, des NA sont automatiquement insérées. Le paramètre optionnel .id permet d’ajouter une colonne (ici nommée source) qui indique la table source des différentes lignes du tableau final.
bind_cols fonctionne de manière similaire :
t1 <- flights %>% slice(1:5) %>% select(dep_delay, dep_time)
t2 <- flights %>% slice(1:5) %>% select(origin, dest)
t3 <- flights %>% slice(1:5) %>% select(arr_delay, arr_time)
bind_cols(t1, t2, t3)À noter que bind_cols associe les lignes uniquement par position. Les lignes des différents tableaux associés doivent donc correspondre (et leur nombre doit donc être identique). Pour associer des tables par valeur, on doit utiliser les jointures.
9.6.2 Jointures
Très souvent, les données relatives à une analyse sont réparties dans plusieurs tables différentes. Dans notre exemple, on peut voir que la table flights contient uniquement les codes des aéroports de départ et d’arrivée :
flights %>% select(origin, dest)Et que par ailleurs la table airports contient des informations supplémentaires relatives à ces aéroports, dont le nom complet, les coordonnées géographiques, etc.
airportsIl est donc naturel de vouloir associer les deux. On peut par exemple vouloir ajouter les noms complets des aéroports à la table flights. Dans ce cas on va faire une jointure : les lignes d’une table seront associées à une autre en se basant non pas sur leur position, mais sur les valeurs d’une ou plusieurs colonnes. Ces colonnes sont appelées des clés.
Commençons par créer une sous-table d’aéroports en ne conservant que la colonne name et en la renommant. On conserve également la colonne faa, qui est la clé nous permettant de faire le lien avec flights :
airports_dep <- airports %>% select(faa, dest_name = name)
airports_depEt une sous-table de vols ne conservant que les colonnes year, month et day, et la clé `dest :
flights_dep <- flights %>% select(year, month, day, dest)
flights_depOn peut alors joindre les deux tables en utilisant la fonction left_join :
left_join(flights_dep, airports_dep, by=c("dest"="faa"))On voit que la table résultat a bien fusionné les deux tables selon les valeurs des deux colonnes clés dest et faa. On est parti de la table flights_dep, et pour chaque ligne on a ajouté les colonnes de airports_dep pour lesquelles la valeur de faa est égale à celle de dest.
L’argument by permet de spécifier les noms des clés si elles ne portent pas le même nom dans les deux tables. On peut l’omettre si c’est le cas. Dans ce cas left_join utilisera comme clés toutes les colonnes présentes dans les deux tables à la fois :
airports_dep <- airports %>% select(dest = faa, dest_name = name)
flights_dep <- flights %>% select(year, month, day, dest)
left_join(flights_dep, airports_dep)## Joining, by = "dest"
À noter qu’on peut continuer à utiliser le pipe avec les fonctions de jointure :
flights_dep %>% left_join(airports_dep)## Joining, by = "dest"
9.6.3 Types de jointures
Jusqu’à présent nous avons utilisé la fonction left_join, mais il existe plusieurs types de jointures.
Partons de deux tables d’exemple, personnes et voitures :
personnes <- data_frame(nom = c("Sylvie", "Sylvie", "Monique", "Gunter", "Rayan", "Rayan"),
voiture = c("Twingo", "Ferrari", "Scenic", "Lada", "Twingo", "Clio"))| nom | voiture |
|---|---|
| Sylvie | Twingo |
| Sylvie | Ferrari |
| Monique | Scenic |
| Gunter | Lada |
| Rayan | Twingo |
| Rayan | Clio |
voitures <- data_frame(voiture = c("Twingo", "Ferrari", "Clio", "Lada", "208"),
vitesse = c(140, 280, 160, 85, 160))| voiture | vitesse |
|---|---|
| Twingo | 140 |
| Ferrari | 280 |
| Clio | 160 |
| Lada | 85 |
| 208 | 160 |
9.6.3.1 left_join
Si on fait un left_join de voitures sur personnes :
left_join(personnes, voitures)## Joining, by = "voiture"
| nom | voiture | vitesse |
|---|---|---|
| Sylvie | Twingo | 140 |
| Sylvie | Ferrari | 280 |
| Monique | Scenic | NA |
| Gunter | Lada | 85 |
| Rayan | Twingo | 140 |
| Rayan | Clio | 160 |
On voit que chaque ligne de personnes est bien présente, et qu’on lui a ajouté une ligne de voitures correspondante si elle existe. Dans le cas du Scenic, il n’y a avait pas de ligne dans voitures, donc vitesse a été mis à NA. Dans le cas de 208, présente dans voitures mais pas dans personnes, la ligne n’apparaît pas.
Si on fait un left_join cette fois de personnes sur voitures, c’est l’inverse :
left_join(voitures, personnes)## Joining, by = "voiture"
| voiture | vitesse | nom |
|---|---|---|
| Twingo | 140 | Sylvie |
| Twingo | 140 | Rayan |
| Ferrari | 280 | Sylvie |
| Clio | 160 | Rayan |
| Lada | 85 | Gunter |
| 208 | 160 | NA |
Cette fois c’est l’inverse. La ligne 208 est là, mais nom est à NA. Par contre Monique est absente. Et on remarquera que la ligne Twingo, présente deux fois dans personnes, a été dupliquée pour être associée aux deux lignes de données de Sylvie et Rayan.
En résumé, quand on fait un left_join(x, y), toutes les lignes de x sont présentes, dupliquées si nécessaire quand elles apparaissent plusieurs fois dans y. Les lignes de y non présentes dans x disparaissent. Les lignes de x non présentes dans y se voient attribuer des NA.
Intuitivement, on pourrait considérer que left_join(x, y) signifie “ramener l’information de la table y sur la table x”.
En général, left_join sera le type de jointures le plus fréquemment utilisé.
9.6.3.2 right_join
La jointure right_join est l’exacte symétrique de left_join, c’est-à dire que right_join(x, y) est équivalent à left_join(x,y) :
right_join(personnes, voitures)## Joining, by = "voiture"
| nom | voiture | vitesse |
|---|---|---|
| Sylvie | Twingo | 140 |
| Rayan | Twingo | 140 |
| Sylvie | Ferrari | 280 |
| Rayan | Clio | 160 |
| Gunter | Lada | 85 |
| NA | 208 | 160 |
9.6.3.3 inner_join
Dans le cas de inner_join(x, y), seules les lignes présentes à la fois dans x et y sont présentes (et si nécessaire dupliquées) dans la table résultat :
inner_join(personnes, voitures)## Joining, by = "voiture"
| nom | voiture | vitesse |
|---|---|---|
| Sylvie | Twingo | 140 |
| Sylvie | Ferrari | 280 |
| Gunter | Lada | 85 |
| Rayan | Twingo | 140 |
| Rayan | Clio | 160 |
Ici la ligne 208 est absente, ainsi que le aligne Monique, qui dans le cas d’un left_join avait été conservée et s’était vue attribuer une vitesse à NA.
9.6.3.4 full_join
Dans le cas de full_join(x, y), toutes les lignes de x et toutes les lignes de y sont conservées (avec des NA ajoutés si nécessaire) même si elles sont absentes de l’autre table :
full_join(personnes, voitures)## Joining, by = "voiture"
| nom | voiture | vitesse |
|---|---|---|
| Sylvie | Twingo | 140 |
| Sylvie | Ferrari | 280 |
| Monique | Scenic | NA |
| Gunter | Lada | 85 |
| Rayan | Twingo | 140 |
| Rayan | Clio | 160 |
| NA | 208 | 160 |
9.6.3.5 semi_join et anti_join
semi_join et anti_join sont des jointures filtrantes, c’est-à-dire qu’elles sélectionnent les lignes de x sans ajouter les colonnes de y.
Ainsi, semi_join ne conservera que les lignes de x pour lesquelles une ligne de y existe également, et supprimera les autres. Dans notre exemple, la ligne Monique est donc supprimée :
semi_join(personnes, voitures)## Joining, by = "voiture"
| nom | voiture |
|---|---|
| Sylvie | Twingo |
| Sylvie | Ferrari |
| Gunter | Lada |
| Rayan | Twingo |
| Rayan | Clio |
Un anti_join fait l’inverse, il ne conserve que les lignes de x absentes de y. Dans notre exemple, on ne garde donc que la ligne Monique :
anti_join(personnes, voitures)## Joining, by = "voiture"
| nom | voiture |
|---|---|
| Monique | Scenic |
9.7 Ressources
Toutes les ressources ci-dessous sont en anglais…
Le livre R for data science, librement accessibles en ligne, contient plusieurs chapitres très complets sur la manipulation des données, notamment :
Le site de l’extension est accessible à l’adresse : http://dplyr.tidyverse.org/. Outre une liste des fonctions et les pages d’aide associées, il contient également une introduction au package et plusieurs articles dont un sur les jointures.
Enfin, une “antisèche” très synthétique est également accessible depuis RStudio, en allant dans le menu Help puis Cheatsheets et Data Transformation with dplyr.
9.8 Exercices
On commence par charger les extensions et les données nécessaires.
library(tidyverse)
library(nycflights13)9.8.1 Les verbes de base de dplyr
Exercice 1.1
Sélectionner les lignes 100 à 105 du tableau des vols (flights).
Exercice 1.2
- Sélectionnez les vols du mois de juillet (variable
month).
- Sélectionnez les vols avec un retard à l’arrivée (variable
arr_delay) compris entre 5 et 15 minutes.
- Sélectionnez les vols des compagnies Delta, United et American (codes
AA,DLetUA).
filter(flights, carrier %in% c("AA", "DL", "UA"))Exercice 1.3
Triez la table flights par retard au départ décroissant.
Exercice 1.4
- Sélectionner les colonnes
name,latetlonde la tableairports
select(airports, name, lat, lon)- Sélectionner toutes les colonnes de la table
airportssauf les colonnestzettzone
select(airports, -tz, -tzone)- Toujours dans la table
airports, renommer la colonnelatenlatitudeetlonenlongitude.
rename(airports, latitude = lat, longitude = lon)Exercice 1.5
Dans la table flights, créer une nouvelle variable duree_h contenant la durée du vol (variable air_time) en heures. Sélectionner dans la table obtenue uniquement les deux colonnes air_time et duree_h.
tmp <- mutate(flights, duree_h = air_time / 60)
select(tmp, air_time, duree_h)9.8.2 Enchaîner des opérations
Exercice 2.1
Réécrire le code de l’exercice précédent en utilisant le pipe %>% :
flights %>%
mutate(duree_h = air_time / 60) %>%
select(air_time, duree_h)Exercice 2.2
Sélectionnez les vols à destination de San Francico (code SFO) et triez-les selon le retard au départ décroissant (variable dep_delay).
Exercice 2.3
Sélectionnez les vols des mois de septembre et octobre, conservez les colonnes dest et dep_delay, créez une nouvelle variables retard_h contenant le retard au départ en heures, triez selon retard_h par ordre décroissant et conservez uniquement les 5 premières lignes.
9.8.3 group_by et summarise
Exercice 3.1
Affichez le nombre de vols par mois.
Triez la table résultat selon le nombre de vols croissant.
Exercice 3.2
Calculer le retard au départ moyen selon le mois.
Exercice 3.3
Calculer le nombre de vols à destination de Los Angeles (code LAX) pour chaque mois de l’année.
Exercice 3.3
Calculer le nombre de vols selon le mois et la destination.
Ne conserver, pour chaque mois, que la destination avec le nombre maximal de vols.
Exercice 3.4
Calculer le nombre de vols selon le mois. Ajouter une colonne comportant le pourcentage de vols annuels réalisés par mois.
Exercice 3.5
Calculer, pour chaque destination et chaque mois, le retard moyen à l’arrivée. Pour chaque mois, trier les destinations selon le retard décroissant, et ne conserver que les trois destinations avec le retard le plus important.
9.8.4 Jointures
Exercice 5.1
Faire la jointure de la table airline sur la table flights à l’aide de left_join.
## Joining, by = "carrier"
Exercice 5.2
À partir de la table résultat de l’exercice précédent, calculer le retard moyen au départ pour chaque compagnie, trier selon ce retard décroissant et afficher le nom de la compagnie et le retard correspondant.
## Joining, by = "carrier"
Exercice 5.3
Faire la jointe de la table airports sur la table flights en utilisant comme clé le code de l’aéroport de destination.
À partir de cette table, afficher pour chaque mois le nom de l’aéroport de destination ayant eu le plus petit nombre de vol.
Exercice 5.4
Créer une table indiquant, pour chaque trajet, le nom de l’aéroport de départ et celui de l’aéroport d’arrivée.
flights %>%
left_join(airports, by = c("dest" = "faa")) %>%
rename(dest_name = name) %>%
left_join(airports, by = c("origin" = "faa")) %>%
rename(orig_name = name) %>%
select(orig_name, dest_name) 9.8.5 Bonus
Exercice 6.1
Calculer le nombre de vols selon l’aéroport de destination, et fusionnez la table airports sur le résultat avec left_join. Stocker le résultat final dans un objet nommé flights_dest.
Créez une carte interactive des résultats avec leaflet et le code suivant :
library(leaflet)
leaflet(data = flights_dest) %>%
addTiles %>%
addCircles(lng=~lon, lat=~lat, radius=~n * 10, popup=~name)Créez une carte statique des résultats avec ggmap et le code suivant :
library(ggmap)
map <- get_map(location = "Kansas", zoom=4, color="bw")
ggmap(map, extent = "device") +
geom_point(data = flights_dest, aes(x=lon, y=lat, size=n),
color = "red", alpha = 0.2)